/*!
 * \file dotnet_remoting_core.c
 *
 * \brief 共通定义
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * 共通使用的宏和结构体
 *
 * \version 1.0
 * \author jikw
 * \date 2015/11/30
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "config.h"
#include "frsutl.h"
#include "frhash2.h"
#include "frreport_comm.h"
#include "frct_comm.h"
#include "frservice_comm.h"
#include "frbyte_buffer.h"
#include "dotnet_remoting_core.h"

extern void *g_p_apm_context;

union int32_float_bits {
    int32_t int_bits;
    float float_bits;
};

union int64_double_bits {
    int64_t int_bits;
    double double_bits;
};

typedef struct OBJECT
{
    char *p_name;                    //对象成员名
    char arr_type[TYPE_LEN];         //对象成员类型
    char arr_type_tmp[TYPE_LEN];     //对象成员类型
}OBJECT;

typedef struct __st_L7session_dotnet_remoting_private
{
    unsigned long ul_seq;                             //序列号，1次req和response时，使用同一个序列号
    L4_transaction st_l4_trans;                       //数据
    Frreport_body_data *p_st_body_data_req;
    Frreport_body_data *p_st_body_data_resp;
    Frlist_header *p_lst_comm;
    Frlist_header *p_lst_req;
    Frbyte_Packet *p_req_packet;
    Frbyte_Packet *p_resp_packet;
}L7session_dotnet_remoting_private;


/*!
 * dotnet_remoting私有数据创建
 *
 * \param void
 *
 * \return NULL          内存分配失败\n
 *         p_st_private  内存分配成功
 *
 * \note
 *
 */
FR_STATIC L7session_dotnet_remoting_private* __dotnet_remoting_private_create(void)
{
    L7session_dotnet_remoting_private *p_st_private = NULL;

    p_st_private = (L7session_dotnet_remoting_private*)frmalloc(sizeof(L7session_dotnet_remoting_private));
    if (p_st_private == NULL)
        return NULL;

    memset(p_st_private, 0x00, sizeof(L7session_dotnet_remoting_private));
    return p_st_private;
}

/*!
 * 私有信息重置
 *
 * \param p_private_session  (dotnet_remoting的私有session数据)
 *
 * \return FR_SUCC   成功\n
 *
 * \note
 *
 */
FR_STATIC int __dotnet_remoting_session_reset(void *p_private_session)
{
    L7session_dotnet_remoting_private *p_st_private = (L7session_dotnet_remoting_private*)p_private_session;

    if (p_st_private)
    {
        if (p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if (p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if (p_st_private->p_lst_req)
            frreport_body_l7list_free(&p_st_private->p_lst_req);

        if (p_st_private->p_lst_comm)
            frreport_body_l7list_free(&p_st_private->p_lst_comm);

        if (p_st_private->p_req_packet)
            bytebuff_free(&(p_st_private->p_req_packet));

        if (p_st_private->p_resp_packet)
            bytebuff_free(&(p_st_private->p_resp_packet));
    }
    return FR_SUCC;
}

/*!
 * 判断是否是dotnet_remoting协议
 *
 * \param p_st_conn      (输入数据信息)
 * \param p_st_packet    (输入数据)
 *
 * \return APM_L7_IS_YES  属于dotnet_remoting协议\n
 *         APM_L7_IS_NO   不属于dotnet_remoting协议
 *
 * \note
 *
 */
int dotnet_remoting_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet)
{
    int i_ret = 0;
    int i_ret_fun = 0;

    if (p_st_packet == NULL || p_st_packet->p_payload == NULL || p_st_packet->ui_payload_len < 10 || p_st_conn==NULL)
        return APM_L7_IS_NO;

    //request以.NET开头
    if (strncmp(p_st_packet->p_payload, ".NET", 4) != 0)
        goto ERROR;
    //主版本号必为0x01,次版本号必为0x00
    if (*(p_st_packet->p_payload+4) != '\x01' || *(p_st_packet->p_payload+5) != '\x00')
        goto ERROR;
    //操作类型可能为0、1、2(0、1为request,2为response)
    if (memcmp(p_st_packet->p_payload+6, "\x00\x00", 2) != 0 && memcmp(p_st_packet->p_payload+6, "\x01\x00", 2) != 0)
        goto ERROR;
    //指定内容是否被分块,必为0x00
    if (memcmp(p_st_packet->p_payload+8, "\x00\x00", 2) != 0)
        goto ERROR;
    //以0x00结尾(2bytes)
    if (memcmp(p_st_packet->p_payload+p_st_packet->ui_payload_len-2, "\x00\x00", 2) != 0)
        goto ERROR;

    i_ret_fun = frct_get_direct_known(p_st_conn);
    if (i_ret_fun == FR_DIRECT_UNKNOWN)
        frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);

    frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);
    return APM_L7_IS_YES;

ERROR:
    if (frct_get_direct_known(p_st_conn) == FR_DIRECT_UNKNOWN)
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
            return APM_L7_IS_YES;
        }
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
            return APM_L7_IS_YES;
        }
    }
    else
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
            return APM_L7_IS_YES;

        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
            return APM_L7_IS_YES;
    }
    return APM_L7_IS_NO;
}

/*!
 * 根据不同类型上报
 *
 * \param p_data          (req数据)
 * \param ui_data_len     (数据长度)
 * \param p_st_private    (私有数据)
 * \param p_st_body_data
 * \param p_st_conn       (入力链接信息)
 *
 * \return FR_SUCC   成功\n
 *         FR_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __add_report(Frbyte_Packet *p_packet
                         , Frreport_body_data *p_st_body_data
                         , char *p_type, char *arr_name)
{
    int i_ret = 0;
    int i_tmp = 0;
    int8_t i8_value = 0;
    int16_t i16_value = 0;
    int32_t i32_value = 0;
    int64_t i64_value = 0;
    uint8_t u8_value = 0;
    uint16_t u16_value = 0;
    uint32_t u32_len = 0;
    uint32_t u32_len_tmp = 0;
    uint64_t u64_value = 0;
    float f_value = 0.0;
    double db_value = 0.0;
    union int32_float_bits u_32bits;
    union int64_double_bits u_64bits;
    char arr_comp[TYPE_LEN];
    char *p_value = NULL;

    if (p_packet == NULL || p_st_body_data == NULL)
        goto ERROR;

    memset(arr_comp, 0x00, sizeof(arr_comp));

    switch (*p_type)
    {
        case DOTNET_REMOTING_DATA_TYPE_BOOL:
            if (bytebuff_get_int(p_packet, 1, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
                goto ERROR;
            if (u32_len == 0 || u32_len == 1)
            {
                if (frreport_body_l7_add_int(p_st_body_data, arr_name, u32_len) == FR_FAIL)
                    goto ERROR;
            }
            else
                goto ERROR;
            break;
        case DOTNET_REMOTING_DATA_TYPE_BYTE:
            if (bytebuff_get_char(p_packet, &u8_value) == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_uint(p_st_body_data, arr_name, u8_value) == FR_FAIL)
                goto ERROR;
            break;
        case DOTNET_REMOTING_DATA_TYPE_SBYTE:
            if (bytebuff_get_char(p_packet, (uint8_t *)&i8_value) == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_int(p_st_body_data, arr_name, i8_value) == FR_FAIL)
                goto ERROR;
            break;
        case DOTNET_REMOTING_DATA_TYPE_CHAR:
            if (bytebuff_get_bytes(p_packet, arr_comp, 1) == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_str(p_st_body_data, arr_name, arr_comp) == FR_FAIL)
                goto ERROR;
            break;
        case DOTNET_REMOTING_DATA_TYPE_NOTUSED:
            if (frreport_body_l7_add_str(p_st_body_data, arr_name, "The value is not used in the protocol") == FR_FAIL)
                goto ERROR;
            break;
        case DOTNET_REMOTING_DATA_TYPE_DECIMAL:
        case DOTNET_REMOTING_DATA_TYPE_STRING:
            if (bytebuff_get_int(p_packet, 1, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
                goto ERROR;
            if (u32_len >= 128)
            {
                for (i_tmp=1; ;i_tmp++)
                {
                    if (bytebuff_get_int(p_packet, 1, &u32_len_tmp, BYTE_LITTLE_ENDIAN) == FR_FAIL)
                        goto ERROR;
                    u32_len += (u32_len_tmp-1) * (int)pow(128.0,(double)i_tmp);
                    if (u32_len_tmp < 128)
                        break;
                }
            }
            p_value = (char*)frmalloc(u32_len+1);
            if (p_value == NULL)
                goto ERROR;
            if (bytebuff_get_bytes(p_packet, p_value, u32_len) == FR_FAIL)
                goto ERROR;
            p_value[u32_len] = '\0';
            if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_value) == FR_FAIL)
                goto ERROR;
            frfree(p_value);
            p_value = NULL;
            break;
        case DOTNET_REMOTING_DATA_TYPE_DOUBLE:
            i_ret = bytebuff_get_long(p_packet, 8, &u64_value, BYTE_LITTLE_ENDIAN);
            if (i_ret == FR_FAIL)
                goto ERROR;
            u_64bits.int_bits = u64_value;
            db_value = u_64bits.double_bits;
            i_ret = frreport_body_l7_add_double(p_st_body_data, arr_name, db_value);
            if (i_ret == FR_FAIL)
                goto ERROR;
            break;
        case DOTNET_REMOTING_DATA_TYPE_INT16:
            i_ret = bytebuff_get_short(p_packet, 2, (uint16_t *)&i16_value, BYTE_LITTLE_ENDIAN);
            if (i_ret == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_int(p_st_body_data, arr_name, i16_value) == FR_FAIL)
                goto ERROR;
            break;
        case DOTNET_REMOTING_DATA_TYPE_UINT16:
            i_ret = bytebuff_get_short(p_packet, 2, &u16_value, BYTE_LITTLE_ENDIAN);
            if (i_ret == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_uint(p_st_body_data, arr_name, u16_value) == FR_FAIL)
                goto ERROR;
            break;
        case DOTNET_REMOTING_DATA_TYPE_INT32:
            i_ret = bytebuff_get_int(p_packet, 4, (uint32_t *)&i32_value, BYTE_LITTLE_ENDIAN);
            if (i_ret == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_int(p_st_body_data, arr_name, i32_value) == FR_FAIL)
                goto ERROR;
            break;
        case DOTNET_REMOTING_DATA_TYPE_UINT32:
            i_ret = bytebuff_get_int(p_packet, 4, &u32_len, BYTE_LITTLE_ENDIAN);
            if (i_ret == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_uint(p_st_body_data, arr_name, u32_len) == FR_FAIL)
                goto ERROR;
            break;
        case DOTNET_REMOTING_DATA_TYPE_INT64:
            i_ret = bytebuff_get_long(p_packet, 8, (uint64_t *)&i64_value, BYTE_LITTLE_ENDIAN);
            if (i_ret == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_long(p_st_body_data, arr_name, i64_value) == FR_FAIL)
                goto ERROR;
            break;
        case DOTNET_REMOTING_DATA_TYPE_UINT64:
            i_ret = bytebuff_get_long(p_packet, 8, &u64_value, BYTE_LITTLE_ENDIAN);
            if (i_ret == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_long(p_st_body_data, arr_name, u64_value) == FR_FAIL)
                goto ERROR;
            break;
        case DOTNET_REMOTING_DATA_TYPE_SINGLE:
            i_ret = bytebuff_get_int(p_packet, 4, &u32_len, BYTE_LITTLE_ENDIAN);
            if (i_ret == FR_FAIL)
                goto ERROR;
            u_32bits.int_bits = u32_len;
            f_value = u_32bits.float_bits;
            i_ret = frreport_body_l7_add_float(p_st_body_data, arr_name, f_value);
            if (i_ret == FR_FAIL)
                goto ERROR;
            break;
        case DOTNET_REMOTING_DATA_TYPE_TIMESPAN:
        case DOTNET_REMOTING_DATA_TYPE_DATATIME:
            i_ret = bytebuff_get_long(p_packet, 8, &u64_value, BYTE_LITTLE_ENDIAN);
            if (i_ret == FR_FAIL)
                goto ERROR;
            i_ret = frreport_body_l7_add_long(p_st_body_data, arr_name, u64_value);
            if (i_ret == FR_FAIL)
                goto ERROR;
            break;
        case DOTNET_REMOTING_DATA_TYPE_NULL:
            if (frreport_body_l7_add_str(p_st_body_data, arr_name, "") == FR_FAIL)
                goto ERROR;
            break;
        default:
            goto ERROR;
    }

    return FR_SUCC;

ERROR:
    if (p_value)
        frfree(p_value);
    return FR_FAIL;
}

/*!
 * 根据不同类型上报
 *
 * \param p_packet        (数据)
 * \param ui_data_len     (数据长度)
 * \param p_st_private    (私有数据)
 * \param p_st_body_data
 * \param i_count
 * \param i_sig
 *
 * \return FR_SUCC   成功\n
 *         FR_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __comm_analysis(Frbyte_Packet *p_packet
                       , unsigned int ui_data_len
                       , L7session_dotnet_remoting_private *p_st_private
                       , Frreport_body_data *p_st_body_data
                       , int i_count,int i_sig)
{
    char arr_type[TYPE_LEN];
    char arr_name[NAME_LEN];

    if (p_packet == NULL || ui_data_len < 1 || p_st_private == NULL || p_st_body_data == NULL)
        return FR_FAIL;

    memset(arr_type, 0x00, sizeof(arr_type));
    memset(arr_name, 0x00, sizeof(arr_name));

    if (i_sig == 0)
        snprintf(arr_name, sizeof(arr_name), "request.dotnet_remoting.arg.%d", i_count+1);
    else if (i_sig == 1)
        snprintf(arr_name, sizeof(arr_name), "response.dotnet_remoting.return.1");
    else
        return FR_FAIL;

    if (bytebuff_get_bytes(p_packet, arr_type, 1) == FR_FAIL)
        return FR_FAIL;

    if (__add_report(p_packet, p_st_body_data, arr_type, arr_name) == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}

/*!
 * 根据不同类型上报
 *
 * \param p_data          (数据)
 * \param ui_data_len     (数据长度)
 * \param p_st_private    (私有数据)
 * \param p_st_body_data
 * \param i_count
 * \param i_sig
 *
 * \return FR_SUCC   成功\n
 *         FR_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __object_analysis(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data, int i_count)
{
    int i_tmp = 0;
    uint32_t u32_len = 0;
    char arr_type[TYPE_LEN];
    char arr_type_tmp[TYPE_LEN];
    char arr_name[NAME_LEN];
    char *p_value = NULL;

    if (p_packet == NULL || p_st_body_data == NULL)
        goto ERROR;

    memset(arr_type, 0x00, sizeof(arr_type));
    memset(arr_name, 0x00, sizeof(arr_name));
    memset(arr_type_tmp, 0x00, sizeof(arr_type_tmp));

    if (bytebuff_get_bytes(p_packet, arr_type, 1) == FR_FAIL)
        goto ERROR;
    if (*arr_type == '\x06')
    {
        snprintf(arr_name, sizeof(arr_name), "request.dotnet_remoting.arg.%d", i_count+1);
        if (bytebuff_skip(p_packet, 4) != FR_SUCC)
            goto ERROR;
        if (bytebuff_get_int(p_packet, 1, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
            goto ERROR;
        p_value = (char*)frmalloc(u32_len+1);
        if (p_value == NULL)
            goto ERROR;
        if (bytebuff_get_bytes(p_packet, p_value, u32_len) == FR_FAIL)
            goto ERROR;
        p_value[u32_len] = '\0';
        if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_value) == FR_FAIL)
            goto ERROR;
        frfree(p_value);
    }
    else if (*arr_type == '\x08')
    {
        snprintf(arr_name, sizeof(arr_name), "request.dotnet_remoting.arg.%d", i_count+1);
        if (bytebuff_get_bytes(p_packet, arr_type_tmp, 1) == FR_FAIL)
            goto ERROR;
        if (__add_report(p_packet, p_st_body_data, arr_type_tmp, arr_name) == FR_FAIL)
            goto ERROR;
    }
    else if (*arr_type == '\x09')
    {
        if (bytebuff_skip(p_packet, 4) != FR_SUCC)
            goto ERROR;
        if (bytebuff_get_bytes(p_packet, arr_type_tmp, 1) == FR_FAIL)
            goto ERROR;
        if (*arr_type_tmp == '\x0f')
        {
            if (bytebuff_skip(p_packet, 4) != FR_SUCC)
                goto ERROR;
            if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
                goto ERROR;
            if (bytebuff_get_bytes(p_packet, arr_type_tmp, 1) == FR_FAIL)
                goto ERROR;
            for (i_tmp = 0; (uint32_t)i_tmp < u32_len; i_tmp++)
            {
                snprintf(arr_name, sizeof(arr_name), "request.dotnet_remoting.arg.%d", i_tmp+1);
                if (__add_report(p_packet, p_st_body_data, arr_type_tmp, arr_name) == FR_FAIL)
                    goto ERROR;
            }
        }
    }
    return FR_SUCC;

ERROR:
    if (p_value)
        frfree(p_value);
    return FR_FAIL;
}

/*!
 * req数据解析
 *
 * \param p_packet        (req数据)
 * \param p_st_private    (私有数据)
 * \param p_st_body_data
 * \param p_st_conn       (入力链接信息)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __req_parse(Frbyte_Packet *p_packet
                        , L7session_dotnet_remoting_private *p_st_private
                        , Frreport_body_data *p_st_body_data
                        , Conntrack *p_st_conn)
{
    int i_count = 0;
    int i_index = 0;
    int i_tmp = 0;
    uint32_t u32_len_t = 0;
    uint32_t u32_len = 0;
    unsigned int ui_len_methodname = 0;
    unsigned int ui_len_typename = 0;
    char arr_type[TEMP_LEN];
    char arr_comp[TEMP_LEN];
    char arr_methodname[NAME_LEN];
    char arr_typename[NAME_LEN];
    char *p_value = NULL;

    if (p_packet == NULL || p_st_private == NULL || p_st_body_data == NULL || p_st_conn == NULL)
        return APM_L7_ANALYZE_FAIL;

    memset(arr_methodname, 0x00, sizeof(arr_methodname));
    memset(arr_typename, 0x00, sizeof(arr_typename));
    memset(arr_type, 0x00, sizeof(arr_type));
    memset(arr_comp, 0x00, sizeof(arr_comp));

    if (bytebuff_skip(p_packet, 10) != FR_SUCC)
        goto ERROR;
    //取总长
    if (bytebuff_get_int(p_packet, 4, &u32_len_t, BYTE_LITTLE_ENDIAN) == FR_FAIL)
        goto ERROR;
    if (bytebuff_skip(p_packet, 4) != FR_SUCC)
        goto ERROR;
    if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
        goto ERROR;
    if (bytebuff_skip(p_packet, u32_len+4) != FR_SUCC)
        goto ERROR;
    if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
        goto ERROR;
    if (bytebuff_skip(p_packet, u32_len+2) != FR_SUCC)
        goto ERROR;

    if ((uint32_t)bytebuff_remaining(p_packet) <  u32_len_t)
        return APM_L7_ANALYZE_TODO;

    //request数据流的结构：RecordTypeEnum(1byte)、TopId(4bytes)、HeaderId(4bytes)、
    //MajorVersion(4byte)、MinorVersion(4byte)
    //跳过p_packet前九位
    if (bytebuff_skip(p_packet, 9) != FR_SUCC)
        goto ERROR;
    //取p_packet的第10、11、12、13位赋给arr_comp
    if (bytebuff_get_bytes(p_packet, arr_comp, 4) == FR_FAIL)
        goto ERROR;
    if (memcmp(arr_comp, "\x01\x00\x00\x00", 4) != 0)
        goto ERROR;
    //取p_packet的第14、15、16、17位赋给arr_comp
    if (bytebuff_get_bytes(p_packet, arr_comp, 4) == FR_FAIL)
        goto ERROR;
    if (memcmp(arr_comp, "\x00\x00\x00\x00", 4) != 0)
        goto ERROR;

    //跳1位 保留4位的enum
    if (bytebuff_skip(p_packet, 1) != FR_SUCC)
        goto ERROR;
    if (bytebuff_get_bytes(p_packet, arr_type, 4) == FR_FAIL)
        goto ERROR;
    if (bytebuff_get_bytes(p_packet, arr_comp, 1) == FR_FAIL)
        goto ERROR;
    //PrimitiveTypeEnum:String'0x12'
    if (*arr_comp != '\x12')
        goto ERROR;

    if (bytebuff_get_int(p_packet, 1, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
        goto ERROR;
    ui_len_methodname = u32_len;

    //将内容取到arr_methodname
    if (bytebuff_get_bytes(p_packet, arr_methodname, ui_len_methodname) == FR_FAIL)
        goto ERROR;

    if (bytebuff_get_bytes(p_packet, arr_comp, 1) == FR_FAIL)
        goto ERROR;
    if (*arr_comp != '\x12')
        goto ERROR;

    if (bytebuff_get_int(p_packet, 1, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
        goto ERROR;
    ui_len_typename = u32_len;

    //寻找'\x2c'逗号，
    //arr_comp[0] = '\x2c';
    i_tmp = bytebuff_getPosition(p_packet);
    if (i_tmp == -1)
        goto ERROR;
    if (bytebuff_memstr(p_packet, bytebuff_getPosition(p_packet), 0, ",", 1, &i_index) == FR_FAIL)
        goto ERROR;

    if (bytebuff_get_bytes(p_packet, arr_typename, i_index-i_tmp) == FR_FAIL)
        goto ERROR;

    p_value = (char*)frmalloc(ui_len_methodname+i_index-i_tmp+1+1);
    if (p_value == NULL)
        goto ERROR;
    //将RemotingObjects.IPerson和getName拼在一起
    snprintf(p_value, ui_len_methodname+i_index-i_tmp+1+1, "%s.%s", arr_typename, arr_methodname);
    if (frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, p_value) == FR_FAIL)
        goto ERROR;
    if (frreport_body_l7_add_str(p_st_body_data, "request.dotnet_remoting.function", p_value) == FR_FAIL)
        goto ERROR;
    frfree(p_value);
    p_value = NULL;

    if (memcmp(arr_type, "\x12\x00\x00\x00", 4) == 0)
    {
        //跳，使p_packet头为参数个数
        if (bytebuff_skip(p_packet, ui_len_typename-i_index+i_tmp) != FR_SUCC)
            goto ERROR;

        if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
            goto ERROR;

        for (i_count = 0; (uint32_t)i_count < u32_len; i_count++)
        {
            if (__comm_analysis(p_packet, bytebuff_remaining(p_packet), p_st_private, p_st_body_data, i_count, 0) == FR_FAIL)
                goto ERROR;
        }
        if (frreport_body_l7_add_int(p_st_body_data, "request.dotnet_remoting.arg.size", i_count) == FR_FAIL)
            goto ERROR;
    }
    if (memcmp(arr_type, "\x14\x00\x00\x00", 4) == 0)
    {
        //跳，使p_packet头为参数个数
        if (bytebuff_skip(p_packet, ui_len_typename-i_index+i_tmp) != FR_SUCC)
            goto ERROR;

        if (bytebuff_skip(p_packet, 5) != FR_SUCC)
            goto ERROR;
        //数量
        if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
            goto ERROR;

        for (i_count = 0; (uint32_t)i_count < u32_len; i_count++)
        {
            if (__object_analysis(p_packet, p_st_body_data, i_count) == FR_FAIL)
                goto ERROR;
        }
        if (frreport_body_l7_add_int(p_st_body_data, "request.dotnet_remoting.arg.size", i_count) == FR_FAIL)
            goto ERROR;
    }

    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);

ERROR:
    if (p_packet)
    {
        bytebuff_free(&p_packet);
        p_st_private->p_req_packet = NULL;
    }
    if (p_value)
        frfree(p_value);

    return APM_L7_ANALYZE_FAIL;
}

FR_STATIC void __object_node_free(Frlist_node *p_st_node)
{
    if (p_st_node == NULL || p_st_node->data == NULL)
        return;

    OBJECT *p_st_data = (OBJECT *)p_st_node->data;

    if (p_st_data->p_name)
        frfree(p_st_data->p_name);

    frfree(p_st_node->data);
    p_st_node->data = NULL;
    return;
}

/*!
 * resp数据解析
 *
 * \param p_packet        (req数据)
 * \param p_st_private    (私有数据)
 * \param p_st_body_data
 * \param p_st_conn       (入力链接信息)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __resp_parse(Frbyte_Packet *p_packet
                         , L7session_dotnet_remoting_private *p_st_private
                         , Frreport_body_data *p_st_body_data
                         , Conntrack *p_st_conn)
{
    int i_count = 0;
    int i_tmp = 0;
    uint32_t u32_len = 0;
    uint32_t u32_len_t = 0;
    char *p_value = NULL;
    char *p_value_object = NULL;
    Frlist_header *p_st_head = NULL;
    Frlist_node *p_st_node = NULL;
    Frlist_node *p_st_node_tmp = NULL;
    OBJECT *p_object = NULL;
    char arr_tmp[TYPE_LEN];
    char arr_comp[TEMP_LEN];
    char arr_name[NAME_LEN];

    if (p_packet == NULL|| p_st_private == NULL || p_st_body_data == NULL || p_st_conn == NULL)
        return APM_L7_ANALYZE_FAIL;

    memset(arr_comp, 0x00, sizeof(arr_comp));
    memset(arr_name, 0x00, sizeof(arr_name));
    memset(arr_tmp, 0x00, sizeof(arr_tmp));

    if (bytebuff_get_bytes(p_packet, arr_comp, 4) == FR_FAIL)
        goto ERROR;
    if (strncmp(arr_comp, ".NET", 4) != 0)
        goto ERROR;

    if (bytebuff_get_bytes(p_packet, arr_comp, 6) == FR_FAIL)
        goto ERROR;
    //主版本、此版本、OperationType
    if (memcmp(arr_comp, "\x01\x00\x02\x00\x00\x00", 6) != 0)
        goto ERROR;

    //取总长
    if (bytebuff_get_int(p_packet, 4, &u32_len_t, BYTE_LITTLE_ENDIAN) == FR_FAIL)
        goto ERROR;
    //跳2位
    if (bytebuff_skip(p_packet, 2) != FR_SUCC)
        goto ERROR;
    if ((uint32_t)bytebuff_remaining(p_packet) <  u32_len_t)
        return APM_L7_ANALYZE_TODO;

    //跳9位，跳过TopId、HeaderId
    if (bytebuff_skip(p_packet, 9) != FR_SUCC)
        goto ERROR;
    //主要版本、次要版本、BinaryHeaderEnum
    if (bytebuff_get_bytes(p_packet, arr_comp, 9) == FR_FAIL)
        goto ERROR;
    if (memcmp(arr_comp, "\x01\x00\x00\x00\x00\x00\x00\x00\x16", 9) != 0)
        goto ERROR;

    if (bytebuff_get_bytes(p_packet, arr_comp, 4) == FR_FAIL)
        goto ERROR;
    if (memcmp(arr_comp, "\x11\x08\x00\x00", 4) == 0)
    {
        if (__comm_analysis(p_packet, bytebuff_remaining(p_packet), p_st_private, p_st_body_data, 0, 1) == FR_FAIL)
            goto ERROR;
    }
    else if (memcmp(arr_comp, "\x11\x10\x00\x00", 4) == 0)
    {
        //if (bytebuff_skip(p_packet, 19) != FR_SUCC)
            //goto ERROR;
        if (bytebuff_skip(p_packet, 14) != FR_SUCC)
            goto ERROR;
        if (bytebuff_get_bytes(p_packet, arr_tmp, 1) == FR_FAIL)
            goto ERROR;
        if (*arr_tmp == '\x0c')
        {
            if (bytebuff_skip(p_packet, 4) != FR_SUCC)
                goto ERROR;
            if (bytebuff_get_int(p_packet, 1, &u32_len_t, BYTE_LITTLE_ENDIAN) == FR_FAIL)
                goto ERROR;
            if (bytebuff_skip(p_packet, u32_len_t) != FR_SUCC)
                goto ERROR;
            //上传对象名
            if (bytebuff_skip(p_packet, 5) != FR_SUCC)
                goto ERROR;
            if (bytebuff_get_int(p_packet, 1, &u32_len_t, BYTE_LITTLE_ENDIAN) == FR_FAIL)
                goto ERROR;
            p_value_object = (char *)frmalloc(u32_len_t+1);
            if (p_value_object == NULL)
                goto ERROR;
            memset(p_value_object, 0x00, u32_len_t+1);
            if (bytebuff_get_bytes(p_packet, p_value_object, u32_len_t) == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_str(p_st_body_data, "response.dotnet_remoting.return.1", p_value_object) == FR_FAIL)
                goto ERROR;
            //frfree(p_value);
            //p_value = NULL;

            //取对象成员数量
            if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
                goto ERROR;
            //取对象成员名字
            for (i_count = 0; (uint32_t)i_count < u32_len; i_count++)
            {
                p_object = (OBJECT *)frmalloc(sizeof(OBJECT));
                memset(p_object, 0x00, sizeof(OBJECT));

                if (bytebuff_get_int(p_packet, 1, &u32_len_t, BYTE_LITTLE_ENDIAN) == FR_FAIL)
                    goto ERROR;
                p_object->p_name = (char *)frmalloc(u32_len_t+1);
                if (p_object->p_name == NULL)
                    goto ERROR;
                memset(p_object->p_name, 0x00, u32_len_t+1);
                if (bytebuff_get_bytes(p_packet, p_object->p_name, u32_len_t) == FR_FAIL)
                    goto ERROR;
                p_st_node = frlist_node_create(p_object);
                if (i_count == 0)
                {
                    p_st_head = frlist_create();
                    frlist_push(p_st_head, p_st_node);
                }
                else
                    frlist_push(p_st_head, p_st_node);
            }
            //取对象成员类型
            for (i_count = 0; (uint32_t)i_count < u32_len; i_count++)
            {
                if (i_count == 0)
                    p_st_node_tmp = FRLIST_FIRST_NODE(p_st_head);
                else
                    p_st_node_tmp = FRLIST_NEXT_NODE(p_st_node_tmp);

                p_object = (OBJECT *) FRLIST_GET_NODE_DATA(p_st_node_tmp);
                if (p_object == NULL)
                    goto ERROR;

                if (bytebuff_get_bytes(p_packet, p_object->arr_type, 1) == FR_FAIL)
                    goto ERROR;
            }
            //成员类型为0时，再次取类型
            for (i_count = 0; (uint32_t)i_count < u32_len; i_count++)
            {
                if (i_count == 0)
                    p_st_node_tmp = FRLIST_FIRST_NODE(p_st_head);
                else
                    p_st_node_tmp = FRLIST_NEXT_NODE(p_st_node_tmp);

                p_object = (OBJECT *) FRLIST_GET_NODE_DATA(p_st_node_tmp);
                if (p_object == NULL)
                    goto ERROR;

                if (*p_object->arr_type == '\x00' || *p_object->arr_type == '\x07')
                {
                    if (bytebuff_get_bytes(p_packet, p_object->arr_type_tmp, 1) == FR_FAIL)
                        goto ERROR;
                }
            }
            if (bytebuff_skip(p_packet, 4) != FR_SUCC)
                goto ERROR;
            //取成员对象值
            for (i_count = 0; (uint32_t)i_count < u32_len; i_count++)
            {
                if (i_count == 0)
                    p_st_node_tmp = FRLIST_FIRST_NODE(p_st_head);
                else
                    p_st_node_tmp = FRLIST_NEXT_NODE(p_st_node_tmp);

                p_object = (OBJECT *) FRLIST_GET_NODE_DATA(p_st_node_tmp);
                if (p_object == NULL)
                    goto ERROR;

                if (*p_object->arr_type == '\x01')
                {
                    if (bytebuff_skip(p_packet, 5) != FR_SUCC)
                        goto ERROR;
                    if (bytebuff_get_int(p_packet, 1, &u32_len_t, BYTE_LITTLE_ENDIAN) == FR_FAIL)
                        goto ERROR;
                    p_value = (char *)frmalloc(u32_len_t+1);
                    if (p_value == NULL)
                        goto ERROR;
                    memset(p_value, 0x00, u32_len_t+1);
                    if (bytebuff_get_bytes(p_packet, p_value, u32_len_t) == FR_FAIL)
                        goto ERROR;
                    snprintf(arr_name, sizeof(arr_name), "response.return.%d.%s.%d.%s", 1, p_value_object, i_count+1, p_object->p_name);
                    if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_value) == FR_FAIL)
                        goto ERROR;
                    frfree(p_value);
                }
                if (*p_object->arr_type == '\x00')
                {
                    snprintf(arr_name, sizeof(arr_name), "response.return.%d.%s.%d.%s", 1, p_value_object, i_count+1, p_object->p_name);
                    if (__add_report(p_packet, p_st_body_data, p_object->arr_type_tmp, arr_name) == FR_FAIL)
                        goto ERROR;
                }
                if (*p_object->arr_type == '\x07')
                {
                    if (bytebuff_skip(p_packet, 10) != FR_SUCC)
                        goto ERROR;
                    if (bytebuff_get_int(p_packet, 4, &u32_len_t, BYTE_LITTLE_ENDIAN) == FR_FAIL)
                        goto ERROR;
                    if (bytebuff_skip(p_packet, 1) != FR_SUCC)
                        goto ERROR;
                    for (i_tmp = 0; (uint32_t)i_tmp < u32_len_t; i_tmp++)
                    {
                        snprintf(arr_name, sizeof(arr_name), "response.return.%d.%s.%d.%s", 1, p_value_object, i_tmp+1, p_object->p_name);
                        if (__add_report(p_packet, p_st_body_data, p_object->arr_type_tmp, arr_name) == FR_FAIL)
                            goto ERROR;
                    }

                }

            }

            frlist_destroy(p_st_head, __object_node_free);
            frfree(p_value_object);
        }
        if (*arr_tmp == '\x0f')
        {
            if (bytebuff_skip(p_packet, 4) != FR_SUCC)
                goto ERROR;

            if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
                goto ERROR;

            if (bytebuff_get_bytes(p_packet, arr_tmp, 1) == FR_FAIL)
                goto ERROR;

            for (i_count = 0; (uint32_t)i_count < u32_len; i_count++)
            {
                snprintf(arr_name, sizeof(arr_name), "response.dotnet_remoting.return.%d", i_count+1);
                if (__add_report(p_packet, p_st_body_data, arr_tmp, arr_name) == FR_FAIL)
                    goto ERROR;
            }
        }
    }
    else
    {
        if (frreport_body_l7_add_str(p_st_body_data, "response.dotnet_remoting.return.1", "") == FR_FAIL)
            goto ERROR;
    }

    if (frreport_body_l7_add_int(p_st_body_data, APM_REPORT_KEY_RESP_CODE, 0) == FR_FAIL)
        goto ERROR;

    if (p_packet)
    {
        bytebuff_free(&p_packet);
        p_st_private->p_resp_packet = NULL;
    }
    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);

ERROR:
    if (p_packet)
    {
        bytebuff_free(&p_packet);
        p_st_private->p_resp_packet = NULL;
    }
    if (p_st_head)
        frlist_destroy(p_st_head, __object_node_free);
    if (p_value_object)
        frfree(p_value_object);

    return APM_L7_ANALYZE_FAIL;
}

/*!
 * dotnet_remoting的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet       (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __req_data_analysis(Conntrack *p_st_conn
                                , Apm_packet *p_st_packet
                                , Frhash_header *p_st_hash_report
                                , L7_session *p_st_session)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7session_dotnet_remoting_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data *p_st_report_data = NULL;
    unsigned long ul_tmp = 0;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_dotnet_remoting_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    //如果连续的两个request
    if (p_st_private->p_lst_comm)
        __dotnet_remoting_session_reset((void *)(p_st_private));

    //创建数据链表
    if (p_st_private->p_st_body_data_req == NULL)
    {
        p_st_private->p_st_body_data_req = frreport_body_new_l7(p_st_conn);
        if (p_st_private->p_st_body_data_req == NULL)
            goto ERROR;

        if (frreport_body_l7_add_connInfo(p_st_private->p_st_body_data_req, p_st_conn) == FR_FAIL)
            goto ERROR;

        //seq ++
        p_st_private->ul_seq = frct_seq_increase(p_st_conn);

        if (p_st_l4_trans->st_request_time_first_byte.tv_sec==0 && p_st_l4_trans->st_request_time_first_byte.tv_usec==0)
        {
            //st_request_time_first_byte
            p_st_l4_trans->st_request_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_l4_trans->st_request_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
        }

        //创建bytebuff
        if (p_st_private->p_req_packet == NULL)
        {
            p_st_private->p_req_packet = bytebuff_creat();
            if (p_st_private->p_req_packet == NULL)
                goto ERROR;
        }
    }

    /* 请求的字节数 */
    p_st_l4_trans->l_request_bytes += p_st_packet->ui_payload_len;

    //把这个包的数据先全加进bytebuff里
    if (bytebuff_add(p_st_private->p_req_packet, p_st_packet->p_payload, p_st_packet->ui_payload_len) != FR_SUCC)
        goto ERROR;

    //req解析
    i_ret = __req_parse(p_st_private->p_req_packet, p_st_private, p_st_private->p_st_body_data_req, p_st_conn);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        return i_ret;
    if (i_ret == APM_L7_ANALYZE_TODO)
    {
        frreport_body_free(&p_st_private->p_st_body_data_req);
        bytebuff_rewind(p_st_private->p_req_packet);
        return i_ret;
    }

    if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_ID, p_st_private->ul_seq) == FR_FAIL)
        goto ERROR;

    //ResponseRequired
    if (frreport_body_l7_add_int(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_ISRESPREQUIRED, 1) == FR_FAIL)
        goto ERROR;

    //start time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_START_TIMESTAMP, &p_st_l4_trans->st_request_time_first_byte) == FR_FAIL)
        goto ERROR;

    //st_request_time
    p_st_l4_trans->st_request_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_request_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    ul_tmp = frtime_diff(&(p_st_l4_trans->st_request_time_first_byte), &(p_st_l4_trans->st_request_time));
    //send_time_us
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_SEND_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //request bytes
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_DATA_BYTES, p_st_l4_trans->l_request_bytes) == FR_FAIL)
        goto ERROR;

    //end time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_END_TIMESTAMP, &p_st_l4_trans->st_request_time) == FR_FAIL)
        goto ERROR;

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_REQ);
    if (p_st_report_data == NULL)
        goto ERROR;

    //拷贝相关链表
    p_st_private->p_lst_comm = FRREPORT_BODY_L7LIST_CLONE_COMM(p_st_private->p_st_body_data_req);
    if (p_st_private->p_lst_comm == NULL)
        goto ERROR;

    p_st_private->p_lst_req = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_private->p_st_body_data_req);
    if (p_st_private->p_lst_req == NULL)
        goto ERROR;

    if (frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_req) == FR_FAIL)
        goto ERROR;
    p_st_private->p_st_body_data_req = NULL;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;
    p_st_report_data = NULL;

    if (p_st_private->p_req_packet)
        bytebuff_free(&p_st_private->p_req_packet);

    return i_ret;

ERROR:
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);
    __dotnet_remoting_session_reset((void *)(p_st_private));
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * dotnet_remoting的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet       (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __resp_data_analysis(Conntrack *p_st_conn
                                 , Apm_packet *p_st_packet
                                 , Frhash_header *p_st_hash_report
                                 , L7_session *p_st_session)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7session_dotnet_remoting_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    unsigned long ul_tmp = 0;
    Frreport_data* p_st_report_data = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_dotnet_remoting_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    if (p_st_private->p_st_body_data_resp == NULL)
    {
        //创建数据链表
        p_st_private->p_st_body_data_resp = frreport_body_new_l7(p_st_conn);
        if (p_st_private->p_st_body_data_resp == NULL)
            goto ERROR;

        if (p_st_l4_trans->st_response_time_first_byte.tv_sec == 0 && p_st_l4_trans->st_response_time_first_byte.tv_usec == 0)
        {
            p_st_l4_trans->st_response_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_l4_trans->st_response_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
        }

        //创建bytebuff
        if (p_st_private->p_resp_packet == NULL)
        {
            p_st_private->p_resp_packet = bytebuff_creat();
            if (p_st_private->p_resp_packet == NULL)
                goto ERROR;
        }
    }
    //请求的字节数
    p_st_l4_trans->l_response_bytes += p_st_packet->ui_payload_len;

    //把这个包的数据先全加进bytebuff里
    if (bytebuff_add(p_st_private->p_resp_packet, p_st_packet->p_payload, p_st_packet->ui_payload_len) != FR_SUCC)
        goto ERROR;

    //resp解析
    i_ret = __resp_parse(p_st_private->p_resp_packet, p_st_private, p_st_private->p_st_body_data_resp, p_st_conn);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        return i_ret;
    if (i_ret == APM_L7_ANALYZE_TODO)
    {
        frreport_body_free(&p_st_private->p_st_body_data_resp);
        p_st_private->p_st_body_data_resp=NULL;
        bytebuff_rewind(p_st_private->p_resp_packet);
        return i_ret;
    }

    //数据上报
    if (p_st_l4_trans->st_request_time_first_byte.tv_sec != 0)
    {
        FRREPORT_BODY_L7LIST_SET_REQ(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_req);
        FRREPORT_BODY_L7LIST_SET_COMM(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_comm);
    }
    else
    {
        if (frreport_body_l7_add_connInfo(p_st_private->p_st_body_data_resp, p_st_conn) == FR_FAIL)
            goto ERROR;
    }
    //start time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_START_TIMESTAMP, &p_st_l4_trans->st_response_time_first_byte) == FR_FAIL)
        goto ERROR;

    if (p_st_l4_trans->st_request_time.tv_sec != 0 || p_st_l4_trans->st_request_time.tv_usec != 0)
    {
        //server time
        ul_tmp = frtime_diff(&(p_st_l4_trans->st_request_time), &(p_st_l4_trans->st_response_time_first_byte));
        if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, ul_tmp) == FR_FAIL)
            goto ERROR;
    }
    else
    {
        if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, 0) == FR_FAIL)
            goto ERROR;
    }

    //st_response_time
    p_st_l4_trans->st_response_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_response_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DATA_BYTES, p_st_l4_trans->l_response_bytes) == FR_FAIL)
        goto ERROR;

    //down load time
    ul_tmp = frtime_diff(&(p_st_l4_trans->st_response_time_first_byte), &(p_st_l4_trans->st_response_time));
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //end time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_END_TIMESTAMP, &p_st_l4_trans->st_response_time) == FR_FAIL)
        goto ERROR;

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_RESP);
    if (p_st_report_data == NULL)
        goto ERROR;

    if (frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_resp) == FR_FAIL)
        goto ERROR;
    p_st_private->p_st_body_data_resp = NULL;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;
    p_st_report_data = NULL;

    __dotnet_remoting_session_reset((void *)(p_st_private));

    return i_ret;

ERROR:
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);
    __dotnet_remoting_session_reset((void *)(p_st_private));
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * dotnet_remoting的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet       (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
int dotnet_remoting_analysis(Conntrack *p_st_conn
                           , Apm_packet *p_st_packet
                           , Frhash_header *p_st_hash_report)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_session *p_st_session = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    /* 到Conntrack中取得session信息 */
    p_st_session = frct_get_session(p_st_conn);
    if (p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    //fin、syn包的话销毁私有数据
    if (p_st_packet->em_analyz_cmd == FRANALYZ_CMD_FIN || p_st_packet->em_analyz_cmd == FRANALYZ_CMD_SYN)
    {
        dotnet_remoting_session_destroy((void *)(p_st_session->p_session_private));
        p_st_session->p_session_private = NULL;
        return APM_L7_ANALYZE_SUCC;
    }

    //p_session_private分配内存
    if (p_st_session->p_session_private == NULL)
    {
        p_st_session->p_session_private = __dotnet_remoting_private_create();
        //内存分配失败
        if (p_st_session->p_session_private == NULL)
            return APM_L7_ANALYZE_FAIL;
    }

    //request
    if (p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV)
    {
        i_ret = __req_data_analysis(p_st_conn,p_st_packet,p_st_hash_report,p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;

        return i_ret;
    }
    else//response
    {
        i_ret = __resp_data_analysis(p_st_conn,p_st_packet,p_st_hash_report, p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;

        return i_ret;
    }

ERROR:
    if (p_st_session->p_session_private)
        dotnet_remoting_session_destroy(p_st_session->p_session_private);
    p_st_session->p_session_private = NULL;
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * 私有信息销毁
 *
 * \param p_private_session  (dotnet_remoting的私有session数据)
 *
 * \return FR_SUCC   成功\n
 *
 * \note
 *
 */
int dotnet_remoting_session_destroy(void *p_private_session)
{
    L7session_dotnet_remoting_private *p_st_private = (L7session_dotnet_remoting_private*)p_private_session;

    if (p_st_private)
    {
        if (p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if (p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if (p_st_private->p_lst_req)
            frreport_body_l7list_free(&p_st_private->p_lst_req);

        if (p_st_private->p_lst_comm)
            frreport_body_l7list_free(&p_st_private->p_lst_comm);

        if (p_st_private->p_req_packet)
            bytebuff_free(&(p_st_private->p_req_packet));

        if (p_st_private->p_resp_packet)
            bytebuff_free(&(p_st_private->p_resp_packet));

        frfree(p_st_private);
    }
    return FR_SUCC;
}
